package com.base.schema.singleton.loophole;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.Constructor;

/**
 * 解决通过反射和序列化、反序列化来破解单例的漏洞
 * @ClassName: SingletonLoophole
 * @Description: 
 * @Author xuyou
 * @DateTime 2021年3月2日 上午10:57:08
 */
public class SingletonLoophole {

	
	public static void main(String[] args) throws Exception {
//		test1();
		test2();
	}
	
	//通过反射来破解单例,可以通过在单例的构造方法里面加对象非空判断,如果非空就抛异常
	public static void test1() throws Exception {
		
		SingletonDemo instance = SingletonDemo.getInstence();
		Class clszz = SingletonDemo.class;
		Constructor con = clszz.getDeclaredConstructor(null);
		con.setAccessible(true);//关闭安全检查,可以调用私有的构造器
		
		SingletonDemo demo = (SingletonDemo) con.newInstance(null);
		System.out.println(instance);
		System.out.println(demo);
	}
	
	
	//通过反序列化来破解单例,可以通过在单例里面增加readResolve这个回调方法
	@SuppressWarnings("resource")
	public static void test2() throws Exception {
		
		SingletonDemo instance = SingletonDemo.getInstence();
		ObjectOutputStream outputStream = new ObjectOutputStream(new FileOutputStream("D:/test.txt"));
		outputStream.writeObject(instance);
		outputStream.flush();
		outputStream.close();
		
		ObjectInputStream inputStream = new ObjectInputStream(new FileInputStream("D:/test.txt"));
		SingletonDemo instance2 = (SingletonDemo) inputStream.readObject();
		
		System.out.println(instance);
		System.out.println(instance2);
	}
}
